import 'dart:async';
import 'dart:convert';
import 'dart:math';

import 'package:dio/dio.dart';
import 'package:flutter/material.dart';
import 'package:flutter/services.dart';
import 'package:shared_preferences/shared_preferences.dart';
import 'package:tv_live/log.dart';

import 'bean.dart';
import 'config.dart';
import 'index.dart';
import 'tv_videoplay.dart';

class TvHomePage extends StatefulWidget {
  const TvHomePage({super.key});

  @override
  State<TvHomePage> createState() => _TvHomePageState();
}

class _TvHomePageState extends MyState<TvHomePage>
    with SingleTickerProviderStateMixin {
  TvDataBean? _tvDataBean;
  List<TvDataBean>? _list;
  bool _hideStuff = false;
  Timer? _hideTimer;
  String defaultTitle = "";
  final marginSize = 5.0;
  final videoKey = GlobalKey(debugLabel: "tv_videoplay_widget");
  final ApiResult _apiResult = ApiResult.init();
  late SharedPreferences prefs;
  final listViewController = ScrollController(debugLabel: "tv_list_view");
  double screenHeight = 0.0;
  final double itemHeight = 36 * 2;

  /// 菜单控制的滚动位置
  int menuScrollerPositon = 0;

  /// listview滚动偏移量
  double scrollOffset = 0.0;
  Timer? scrollUpdateTimer;
  @override
  void initState() {
    super.initState();
    SystemChrome.setPreferredOrientations([
      DeviceOrientation.landscapeLeft,
      DeviceOrientation.landscapeRight,
    ]);
    SystemChrome.setEnabledSystemUIMode(SystemUiMode.manual, overlays: []);
    SystemChrome.setSystemUIOverlayStyle(const SystemUiOverlayStyle());
    initData();
  }

  void checkUpdatePosition() {
    if (listViewController.offset <= screenHeight / 2) return;
    double positionD =
        (listViewController.offset + screenHeight / 2) / itemHeight;
    int position = positionD.toInt();
    // print("TAG positionD=$positionD position=$position");
    if (position != menuScrollerPositon && _list?.isNotEmpty == true) {
      // 当滚动后的postion 大于 点击控制的position时 需要更新
      itemClick(_list![position], position);
    }
  }

  void initData() async {
    prefs = await SharedPreferences.getInstance();
    defaultTitle = prefs.getString("defaultTitle") ?? "";
    var list = await loadData();
    setState(() {
      // 显示频道列表
      _showStuff();
      _apiResult.success();
      _list = list;
      var index =
          list.firstWhereIndex((e) => e.title == defaultTitle, orElse: () => 0);
      _tvDataBean = list[index];
      Future.delayed(const Duration(milliseconds: 100), () {
        _scrollerToIndex(index, true);
      });
    });
  }

  /// 显示频道列表 [state]-->是否刷洗
  void _showStuff([bool state = false]) {
    void update() {
      if (_hideStuff == true) {
        _hideStuff = false;
      }
      _hideTimer?.cancel();
      _hideTimer = Timer(const Duration(seconds: 5), _closeStuff);
    }

    if (state) {
      setState(update);
    } else {
      update();
    }
  }

  /// 关闭频道列表
  void _closeStuff() {
    print("TAG _closeStuff _hideStuff=$_hideStuff");
    if (!_hideStuff) {
      setState(() {
        _hideStuff = true;
        _hideTimer = null;
      });
    }
  }

  Future<List<TvDataBean>> loadData() async {
    var res = await Dio(BaseOptions(
      connectTimeout: const Duration(seconds: timeout),
      sendTimeout: const Duration(seconds: timeout),
      receiveTimeout: const Duration(seconds: timeout),
    )).get(TV_URL).catchError((err) {
      if (err is DioException) {
        return err.response ??
            Response(
              requestOptions: err.requestOptions,
              statusMessage: err.message ?? "未知错误",
              statusCode: 404,
              data: "",
            );
      }
      return Response<String>(
        requestOptions: RequestOptions(),
        statusMessage: err.toString(),
        statusCode: 404,
        data: "",
      );
    });

    List<TvDataBean> list;
    if (res.statusCode != 200) {
      var data = await rootBundle.loadString("assets/data/index.txt");
      list = TvDataBean.parseTxt(data);
    } else {
      var data = res.data!;
      try {
        Map map;
        if (data is Map) {
          map = data;
        } else {
          map = jsonDecode(data);
        }
        var bean = TvLiveBean.fromJson(map);
        list = bean.list;
      } catch (e, s) {
        Log.e(e, stackTrace: s);
        data = await rootBundle.loadString("assets/data/index.txt");
        list = TvDataBean.parseTxt(data);
      }
    }
    list.insert(
        0,
        const TvDataBean(urls: [
          'https://vip.dytt-cinema.com/20250804/29128_24f1f625/3000k/hls/mixed.m3u8'
        ], title: '测试频道'));
    return list;
  }

  @override
  Widget build(BuildContext context) {
    return SafeArea(
        child: Scaffold(
      body: bodyView(context),
    ));
  }

  Widget bodyView(BuildContext context) {
    Size size = MediaQuery.sizeOf(context);
    var width = size.width;
    screenHeight = size.height;
    var boxWidth = min(width, size.height) / 4;
    return Focus(
      autofocus: true,
      canRequestFocus: true,
      descendantsAreFocusable: true,
      onKeyEvent: onKeyEvent,
      child: Container(
        color: Colors.black,
        child: Stack(children: [
          if (_apiResult.isSuccess)
            // video
            Align(alignment: Alignment.center, child: videoView(context)),
          if (_apiResult.isInit || _apiResult.isLoading)
            Align(
                alignment: Alignment.center,
                child: SizedBox(
                  width: boxWidth,
                  height: boxWidth,
                  child: const CircularProgressIndicator(
                    color: Colors.blue,
                    strokeWidth: circle_progress_width,
                  ),
                )),
          // 菜单
          AnimatedOpacity(
              opacity: _hideStuff ? 0.0 : 1.0,
              duration: const Duration(milliseconds: 200),
              child: Align(
                  alignment: Alignment.topLeft, child: menuView(context))),
        ]),
      ),
    );
  }

  Widget videoView(BuildContext context) {
    return TvVideoplayWidget(
      key: videoKey,
      urls: _tvDataBean?.urls ?? [],
      header: _tvDataBean?.header,
    );
  }

  Widget menuView(BuildContext context) {
    return Container(
      color: Colors.black.withOpacity(0.3),
      width: 300,
      child: AbsorbPointer(
        absorbing: _hideStuff,
        child: ListView.builder(
          controller: listViewController,
          padding: const EdgeInsets.only(top: 4, bottom: 4),
          itemBuilder: itemBuilder,
          itemCount: _list?.length ?? 0,
        ),
      ),
    );
  }

  Widget itemBuilder(BuildContext context, int index) {
    var bean = _list![index];
    return InkWell(
      onTap: () => itemClick(bean, index),
      child: Container(
        padding: const EdgeInsets.only(left: 15),
        alignment: Alignment.centerLeft,
        width: 300,
        height: itemHeight,
        child: Text(
          bean.title,
          style: TextStyle(
            color:
                _tvDataBean?.title == bean.title ? Colors.blue : Colors.white,
            fontSize: 30,
            fontWeight: FontWeight.bold,
          ),
        ),
      ),
    );
  }

  void itemClick(TvDataBean bean, int index) {
    setState(() {
      _tvDataBean = bean;
    });
    defaultTitle = bean.title;
    prefs.setString("defaultTitle", bean.title);
  }

  void _scrollerToPosition(bool upTag) {
    if (_list?.isNotEmpty != true || screenHeight < 1) return;
    int position = _list!
        .firstWhereIndex((e) => e.title == _tvDataBean?.title, orElse: () => 0);
    menuScrollerPositon = position;
    // 第一向上 最后向下
    if ((position == 0 && upTag) || position == _list!.length && !upTag) return;
    /* if (position == 0 && upTag) {
      var index = _list!.length - 1;
      listViewController.jumpTo(_list!.length * itemHeight - screenHeight);
      itemClick(_list![index], index);
      return;
    }
    if (position == _list!.length && !upTag) {
      var index = 0;
      listViewController.jumpTo(0);
      itemClick(_list![index], index);
      return;
    } */
    position = upTag ? position - 1 : position + 1;
    menuScrollerPositon = position;
    // print("TAG position=$position");
    _scrollerToIndex(position);
  }

  void _scrollerToIndex(int index, [bool inInit = false]) {
    if (_list?.isNotEmpty != true || screenHeight < 1) return;
    if (index < 0 || index >= _list!.length) return;
    var offset = index * itemHeight - screenHeight / 2;
    print(
        "TAG offset=$offset listViewController.offset=${listViewController.offset} ${listViewController.offset + offset}");
    if (listViewController.offset + offset > 0 &&
        offset < itemHeight * _list!.length - screenHeight) {
      listViewController.animateTo(
        offset,
        duration: const Duration(milliseconds: 300),
        curve: Curves.easeIn,
      );
    }
    if (!inInit) itemClick(_list![index], index);
  }

  KeyEventResult onKeyEvent(FocusNode node, KeyEvent event) {
    var logicalKey = event.logicalKey;
    if (event is KeyUpEvent) {
      // print(
      //     "up logicalKey=$logicalKey debugLabel=${d.focusNode.debugLabel}");
      // 按键抬起
      if (logicalKey == LogicalKeyboardKey.enter ||
          logicalKey == LogicalKeyboardKey.select) {
        // 确认按钮
        return KeyEventResult.handled;
      }
      if (logicalKey == LogicalKeyboardKey.arrowUp) {
        checkUpdatePosition();
        return KeyEventResult.handled;
      }
      if (logicalKey == LogicalKeyboardKey.arrowDown) {
        checkUpdatePosition();
        return KeyEventResult.handled;
      }
    } else if (event is KeyDownEvent) {
      // 按键按下
      if (logicalKey == LogicalKeyboardKey.enter ||
          logicalKey == LogicalKeyboardKey.select) {
        // 确认按钮
        return KeyEventResult.handled;
      }
      if (logicalKey == LogicalKeyboardKey.arrowUp) {
        _showStuff(true);
        _scrollerToPosition(true);
        return KeyEventResult.handled;
      }
      if (logicalKey == LogicalKeyboardKey.arrowDown) {
        _showStuff(true);
        _scrollerToPosition(false);
        return KeyEventResult.handled;
      }
    }
    return KeyEventResult.ignored;
  }
}

// ignore: camel_case_extensions
extension findList<E> on List<E> {
  int firstWhereIndex(bool Function(E element) test, {int Function()? orElse}) {
    for (int index = 0; index < length; index++) {
      E element = this[index];
      if (test(element)) return index;
    }
    if (orElse != null) return orElse();
    return 0;
  }
}
